home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 30
/
Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso
/
Aminet
/
util
/
pack
/
xpk_Source.lha
/
xpk_Source
/
xpkmaster
/
open.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-11-09
|
15KB
|
475 lines
#ifndef XPKMASTER_OPEN_C
#define XPKMASTER_OPEN_C
/* Routinesheader
Name: open.c
Main: xpkmaster
Versionstring: $VER: open.c 1.19 (30.10.1998)
Author: SDI
Distribution: Freeware
Description: Opening and initialisation routines for XPK files
1.0 06.10.96 : first real version
1.1 28.10.96 : reincluded A4 support
1.2 03.03.97 : added Prefs, corrected length recognition
1.3 07.03.97 : fixed prefs handling, new features
1.4 09.03.97 : added DEBUG statement
1.5 28.03.97 : auto decrunch password
1.6 29.03.97 : fixed prefs stuff, moved getinlen into hooks
1.7 31.03.97 : changed the password stuff
1.8 19.12.97 : added xfdmaster.library support
1.9 22.12.97 : fixed auto password problem
1.10 27.12.97 : fixed GetPassword error
1.11 09.01.98 : better key handling
1.12 21.01.98 : added password verification for packing
1.13 24.01.98 : fixed xfdmaster support a bit
1.14 17.02.98 : fixe long file problem added in last version
1.15 21.02.98 : uses new style register definition
1.16 26.03.98 : some optimizations
1.17 26.08.98 : may skip reading insize for packing, when no inhook
1.18 13.09.98 : removed PP stuff
1.19 30.10.98 : some changes for seek support
*/
#include <xpk/xpkprefs.h>
#include <exec/memory.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/xpkmaster.h>
#include <proto/xpksub.h>
#include <proto/xfdmaster.h>
#include "xpkmaster.h"
#include "texts.h"
static const struct XpkInfo DONTInfo = { 1,0,0,1,"DONT","Copy",
0, 0x55534552, XPKIF_PK_CHUNK|XPKIF_UP_CHUNK, DEFAULTCHUNKSIZE, 1,
DEFAULTCHUNKSIZE,0,0,0,0,100,0,0,0,0,0,0,0,0};
/* XpkMode is not initialized! Should not be used anywhere */
static LONG xpkopenwrite(struct XpkBuffer **, struct TagItem *);
static LONG GetPrefsPacker(struct XpkBuffer *);
static LONG GetPassword(struct XpkBuffer *, struct TagItem *, ULONG);
static struct XpkTypeData *BufRecog(ULONG, struct XpkBuffer *,
struct XpkPrefsSemaphore *);
XPK_ALLINONE ASM(LONG) xpkopen(REG(a0, struct XpkBuffer **xbufp),
REG(a1, struct TagItem *tags), REG(d2, ULONG examine A4PROTO))
{
struct XpkBuffer *xbuf;
struct XpkStreamHeader *globhdr;
struct XpkFib *fib;
#if defined(DEBUG) && defined(SUPPORT_A4)
DebugRunTime("xpkopen: A4 = %ld", a4);
#elif defined (DEBUG)
DebugRunTime("xpkopen");
#endif
if(!(*xbufp = xbuf = initxbuf()))
return parseerrortags(tags, XPKERR_NOMEM);
#ifdef SUPPORT_A4
xbuf->xb_regA4 = a4;
#endif
globhdr = &xbuf->xb_Headers.h_Glob;
fib = &xbuf->xb_Fib;
if(parsebuftags(xbuf, tags))
goto Abort;
if(xbuf->xb_Flags & XMF_PACKING) /* Call pack open function */
return xpkopenwrite(xbufp, tags);
if(!hookread(xbuf, XIO_READ, globhdr, 4)) /* Read first longword */
{
if(xbuf->xb_Result != XPKERR_TRUNCATED)
goto Abort;
/* else handle now as uncompressed file */
}
/***************************** Standard XPK file **********************/
if(globhdr->xsh_Pack == XPK_COOKIE)
{
UWORD exthlen = 0; /* size of extended header if present */
struct Library * XpkSubBase;
xbuf->xb_Format = XPKMODE_UPSTD;
/* Read rest of the global header */
if(!hookread(xbuf, XIO_READ, (STRPTR) globhdr + 4, sizeof(struct XpkStreamHeader) - 4))
goto Abort;
if(hchecksum((STRPTR) globhdr, sizeof(struct XpkStreamHeader)))
{
xbuf->xb_Result = XPKERR_CHECKSUM;
goto Abort;
}
if(globhdr->xsh_Flags & XPKSTREAMF_LONGHEADERS)
xbuf->xb_Headers.h_LocSize = sizeof(struct XpkChunkHdrLong);
else
xbuf->xb_Headers.h_LocSize = sizeof(struct XpkChunkHdrWord);
if(globhdr->xsh_Flags & XPKSTREAMF_EXTHEADER)
{
if(!hookread(xbuf, XIO_READ, &exthlen, sizeof(UWORD)))
goto Abort;
if(!hookread(xbuf, XIO_READ, NULL, exthlen))
goto Abort;
exthlen += sizeof(UWORD); /* for unwinding while XpkExamine */
}
if(!hookread(xbuf, XIO_READ, &xbuf->xb_Headers.h_Loc,
xbuf->xb_Headers.h_LocSize)) /* first lochdr */
goto Abort;
fib->xf_CCur = sizeof(struct XpkStreamHeader);
if(updatefib(xbuf))
goto Abort;
xbuf->xb_InLen = fib->xf_CLen;
if(!(XpkSubBase = opensub(xbuf, globhdr->xsh_Type)))
goto Abort;
if(globhdr->xsh_SubVrs > xbuf->xb_SubInfo->xi_LibVersion)
{
xbuf->xb_Result = XPKERR_OLDSUBLIB;
goto Abort;
}
xbuf->xb_Prog.xp_Activity = xbuf->xb_SubInfo->xi_UnpackMsg ?
xbuf->xb_SubInfo->xi_UnpackMsg : strings[TXT_UNPACKING_UPPER];
xbuf->xb_Prog.xp_PackerName = xbuf->xb_SubInfo->xi_Name;
xbuf->xb_LastMsg = xbuf->xb_SubInfo->xi_UnpackedMsg ?
xbuf->xb_SubInfo->xi_UnpackedMsg : strings[TXT_UNPACKED];
if(globhdr->xsh_Flags & XPKSTREAMF_PASSWORD)
fib->xf_Flags |= XPKFLAGS_PASSWORD;
if(examine && !hookread(xbuf, XIO_SEEK, 0,
-(sizeof(struct XpkStreamHeader) + xbuf->xb_Headers.h_LocSize+exthlen)))
goto Abort;
goto Exit;
}
if(!hookread(xbuf, XIO_SEEK, 0, -xbuf->xb_RMsg.xmm_Size))
goto Abort; /* redo last read bytes */
if(xbuf->xb_InLen == 0xFFFFFFFF)
{
if(!hookread(xbuf, XIO_TOTSIZE, 0, 0)) /* get input length */
goto Abort;
else if(xbuf->xb_RMsg.xmm_Size)
xbuf->xb_InLen = xbuf->xb_RMsg.xmm_Size;
}
fib->xf_CLen = xbuf->xb_InLen;
/**************************** xfdmaster file **************************/
if(xbuf->xb_Flags & XMF_XFD &&
(xbuf->xb_SubBase = OpenLibrary("xfdmaster.library", 38)))
{
struct xfdMasterBase *xfdMasterBase = (struct xfdMasterBase *) xbuf->xb_SubBase;
struct xfdBufferInfo *xbi;
if(!(xbi = xbuf->xb_xfd = (struct xfdBufferInfo *) xfdAllocObject(XFDOBJ_BUFFERINFO)))
goto Abort;
if(!(xbi->xfdbi_SourceBuffer = hookread(xbuf, XIO_READ, 0, xbuf->xb_InLen)))
goto Abort;
xbi->xfdbi_SourceBufLen = xbuf->xb_InLen;
xbi->xfdbi_Flags = XFDFF_RECOGEXTERN|XFDFF_RECOGTARGETLEN|XFDFF_RECOGUSERTARGET;
if(xfdRecogBuffer(xbi) && (xbi->xfdbi_PackerFlags & XFDPFF_DATA) &&
(LONG) xbi->xfdbi_FinalTargetLen != -1)
{
xbuf->xb_Format = XPKMODE_UPXFD;
if(xbi->xfdbi_PackerFlags & XFDPFF_PASSWORD)
xbuf->xb_Fib.xf_Flags |= XPKFLAGS_PASSWORD;
if(xbi->xfdbi_PackerFlags & XFDPFF_KEY16)
xbuf->xb_Fib.xf_Flags |= XPKFLAGS_KEY16;
if(xbi->xfdbi_PackerFlags & XFDPFF_KEY32)
xbuf->xb_Fib.xf_Flags |= XPKFLAGS_KEY32;
fib->xf_Type = XPKTYPE_PACKED;
fib->xf_ULen = xbi->xfdbi_FinalTargetLen;
fib->xf_NLen = xbi->xfdbi_MinTargetLen;
fib->xf_ID = XFD_COOKIE;
percentages(fib);
xbuf->xb_Prog.xp_Activity = strings[TXT_UNPACKING_UPPER];
xbuf->xb_Prog.xp_PackerName = "XFDMaster";
xbuf->xb_LastMsg = strings[TXT_UNPACKED];
if(examine && !hookread(xbuf, XIO_SEEK, 0, -xbuf->xb_InLen))
goto Abort; /* return to start */
#ifdef DEBUG
DebugRunTime("xpkopen: XFD, InLen %ld, OutLen %ld, NLen %ld",
xbuf->xb_InLen, fib->xf_ULen, fib->xf_NLen);
#endif
goto Exit;
} /* xfdRecogBuffer */
if(!hookread(xbuf, XIO_SEEK, 0, -xbuf->xb_InLen))
goto Abort; /* return to start */
}
/*************************** Uncompressed file ************************/
if(examine || xbuf->xb_Flags & XMF_PASSTHRU) /* Unpacked */
{
xbuf->xb_Format = XPKMODE_UPUP;
fib->xf_Type = XPKTYPE_UNPACKED;
fib->xf_ULen = xbuf->xb_InLen;
fib->xf_NLen = Min(DEFAULTCHUNKSIZE, xbuf->xb_InLen) + XPK_MARGIN;
fib->xf_ID = ROW_OF_MINUS;
xbuf->xb_Prog.xp_Activity = strings[TXT_READING];
xbuf->xb_Prog.xp_PackerName = "Master";
xbuf->xb_LastMsg = strings[TXT_READ];
xbuf->xb_Result = XPKERR_OK; /* if != 0 it was XPKERR_TRUNCATED */
goto Exit;
}
xbuf->xb_Result = XPKERR_NOTPACKED; /* Can't unpack, can't passthru */
Abort:
*xbufp = 0;
return XpkClose((struct XpkFib *) xbuf);
Exit:
if(!examine && (
((fib->xf_Flags & XPKFLAGS_PASSWORD) && !xbuf->xb_Password) ||
((fib->xf_Flags & XPKFLAGS_KEY16) && !(xbuf->xb_Flags & XMF_KEY16)) ||
((fib->xf_Flags & XPKFLAGS_KEY32) && !(xbuf->xb_Flags & XMF_KEY32)))
&& (xbuf->xb_Result = GetPassword(xbuf, tags, FALSE)))
goto Abort;
return XPKERR_OK;
}
/***************************** Open for packing *************************/
static LONG xpkopenwrite(struct XpkBuffer **xbufp, struct TagItem *tags)
{
struct XpkBuffer *xbuf = *xbufp;
struct XpkStreamHeader *globhdr = &xbuf->xb_Headers.h_Glob;
struct Library *XpkSubBase;
LONG res;
xbuf->xb_Format = XPKMODE_PKSTD;
if(xbuf->xb_InLen == 0xFFFFFFFF && xbuf->xb_RHook)
{
if(!hookread(xbuf, XIO_TOTSIZE, 0, 0)) /* get input length */
return xbuf->xb_Result;
else if(xbuf->xb_RMsg.xmm_Size)
xbuf->xb_InLen = xbuf->xb_RMsg.xmm_Size;
}
if(!(XpkSubBase = xbuf->xb_SubBase) && /* Do we know the sublib? */
(xbuf->xb_Result = GetPrefsPacker(xbuf)))
goto Abort; /* no sublib and no prefs packer finder */
if(xbuf->xb_Password && !(xbuf->xb_SubInfo->xi_Flags & XPKIF_ENCRYPTION))
{
xbuf->xb_Result = XPKERR_NOCRYPT;
goto Abort;
}
if(!xbuf->xb_Password && (xbuf->xb_SubInfo->xi_Flags & XPKIF_NEEDPASSWD))
{ /* automatic password requester */
if((xbuf->xb_Result = GetPassword(xbuf, tags, TRUE)))
goto Abort;
}
if(!(xbuf->xb_Flags & XMF_LOSSYOK) &&
xbuf->xb_SubInfo->xi_Flags & XPKIF_LOSSY)
{
xbuf->xb_Result = XPKERR_LOSSY;
goto Abort;
}
if(xbuf->xb_PackingMode > 100) /* Is packing mode valid? */
xbuf->xb_PackingMode = 100; /* Use max */
if(xbuf->xb_InLen != 0xFFFFFFFF)
{
if(!hookwrite(xbuf, XIO_TOTSIZE, 0, ROUNDLONG
(xbuf->xb_InLen + (xbuf->xb_InLen >> 5)) + (XPK_MARGIN<<1)))
goto Abort;
}
/************************* Find the chunk size ************************/
if((xbuf->xb_ChunkSize == 0) &&
((xbuf->xb_ChunkSize = xbuf->xb_SubInfo->xi_DefPkInChunk) == 0))
xbuf->xb_ChunkSize = DEFAULTCHUNKSIZE;
if(xbuf->xb_ChunkSize < xbuf->xb_SubInfo->xi_MinPkInChunk)
xbuf->xb_ChunkSize = xbuf->xb_SubInfo->xi_MinPkInChunk;
if((xbuf->xb_SubInfo->xi_MaxPkInChunk) &&
(xbuf->xb_ChunkSize > xbuf->xb_SubInfo->xi_MaxPkInChunk))
xbuf->xb_ChunkSize = xbuf->xb_SubInfo->xi_MaxPkInChunk;
/************************ Prepare global header ***********************/
globhdr->xsh_Pack = 0; /* Initialize the global header */
globhdr->xsh_Type = xbuf->xb_SubID;
if(xbuf->xb_ChunkSize > 65000) /* (0xFFFF-XPK_MARGIN) and some bytes security */
globhdr->xsh_Flags |= XPKSTREAMF_LONGHEADERS;
if(xbuf->xb_Password)
globhdr->xsh_Flags |= XPKSTREAMF_PASSWORD;
xbuf->xb_Headers.h_LocSize = globhdr->xsh_Flags & XPKSTREAMF_LONGHEADERS
? sizeof (struct XpkChunkHdrLong)
: sizeof (struct XpkChunkHdrWord);
memset(globhdr->xsh_Initial, 0xff, 16); /* Read first 16 bytes */
xbuf->xb_Prog.xp_Activity = xbuf->xb_SubInfo->xi_PackMsg ?
xbuf->xb_SubInfo->xi_PackMsg : strings[TXT_PACKING_UPPER];
xbuf->xb_Prog.xp_PackerName = xbuf->xb_SubInfo->xi_Name;
xbuf->xb_LastMsg = xbuf->xb_SubInfo->xi_PackedMsg ?
xbuf->xb_SubInfo->xi_PackedMsg : strings[TXT_PACKED];
Abort:
xbuf->xb_Fib.xf_NLen = Min(xbuf->xb_InLen - xbuf->xb_Fib.xf_UCur,
xbuf->xb_ChunkSize);
if((res = xbuf->xb_Result))
res = XpkClose((struct XpkFib *) xbuf);
return res;
}
typedef ASM(struct XpkTypeData *) (*RecogFunc) (REG(a0, STRPTR),
REG(a1, STRPTR), REG(d0, ULONG), REG(d1, ULONG),
REG(a2, struct TagItem *));
static LONG GetPrefsPacker(struct XpkBuffer *xbuf)
{
LONG ret = XPKERR_UNKNOWN;
struct XpkPrefsSemaphore *sem;
ULONG bufsize;
struct XpkTypeData *td = 0;
if((xbuf->xb_Flags & XMF_NOPREFS) || !xbuf->xb_RHook)
return XPKERR_BADPARAMS;
if(!(sem = GetPrefsSem()))
return XPKERR_NOFUNC;
bufsize = Min(xbuf->xb_InLen, sem->xps_RecogSize);
if(sem->xps_RecogFunc && (td = BufRecog(bufsize, xbuf, sem)) ==
(struct XpkTypeData *) 0xFFFFFFFF)
td = BufRecog(xbuf->xb_InLen, xbuf, sem);
if(!td || td == (struct XpkTypeData *) 0xFFFFFFFF)
td = sem->xps_MainPrefs ? sem->xps_MainPrefs->xmp_DefaultType : 0;
if(td)
{
if(td->xtd_Flags & XTD_NoPack)
{
xbuf->xb_Flags |= XMF_NOPACK;
xbuf->xb_SubInfo = (struct XpkInfo *) &DONTInfo;
ret = XPKERR_OK;
}
else if(!(td->xtd_Flags & XTD_ReturnError))
{
struct Library *XpkSubBase;
struct XpkInfo *subinfo;
if((XpkSubBase = opensub(xbuf, td->xtd_StdID)))
{
ret = XPKERR_OK;
subinfo = XpksPackerInfo();
xbuf->xb_ChunkSize = td->xtd_ChunkSize;
xbuf->xb_PackingMode = ( td->xtd_Mode ? td->xtd_Mode :
subinfo->xi_DefMode);
// if(!(xbuf->xb_Password) && td->xtd_Password &&
// (xbuf->xb_PasswordSize = strlen(td->xtd_Password)))
// {
// /* we need a buffer including end byte! --> ++size */
// if(!(xbuf->xb_Password = (STRPTR)
// AllocMem(++xbuf->xb_PasswordSize, MEMF_PUBLIC)))
// ret = XPKERR_NOMEM;
// else
// {
// xbuf->Flags |= XMF_OWNPASSWORD;
// CopyMem(td->xtd_Password, xbuf->xb_Password, xbuf->xb_PasswordSize);
// }
// }
}
}
else
ret = XPKERR_NOMETHOD;
}
if(td->xtd_Memory && td->xtd_MemorySize)
FreeMem(td->xtd_Memory, td->xtd_MemorySize);
ReleaseSemaphore((struct SignalSemaphore *) sem);
return ret;
}
static LONG GetPassword(struct XpkBuffer *xbuf, struct TagItem *tags,
ULONG verify)
{
if(xbuf->xb_Flags & XMF_AUTOPASSWD)
{
if(xbuf->xb_Fib.xf_Flags & XPKFLAGS_KEY32)
{
xbuf->xb_Result = XpkPassRequestTags(XPK_Key32BitPtr,
&xbuf->xb_PassKey32, TAG_MORE, tags, TAG_DONE);
xbuf->xb_Flags |= XMF_KEY32;
}
else if(xbuf->xb_Fib.xf_Flags & XPKFLAGS_KEY16)
{
xbuf->xb_Result = XpkPassRequestTags(XPK_Key16BitPtr,
&xbuf->xb_PassKey16, TAG_MORE, tags, TAG_DONE);
xbuf->xb_Flags |= XMF_KEY16;
}
else
{
if(!(xbuf->xb_Password = (STRPTR) AllocMem(AUTO_PASS_SIZE, MEMF_PUBLIC)))
return XPKERR_NOMEM;
xbuf->xb_PasswordSize = AUTO_PASS_SIZE;
xbuf->xb_Flags |= XMF_OWNPASSWORD; /* must be freed later */
xbuf->xb_Result = XpkPassRequestTags(XPK_PasswordBuf,
xbuf->xb_Password, XPK_PassBufSize, xbuf->xb_PasswordSize,
XPK_PassVerify, verify, TAG_MORE, tags, TAG_DONE);
}
return xbuf->xb_Result;
}
return XPKERR_NEEDPASSWD;
}
static struct XpkTypeData *BufRecog(ULONG bufsize, struct XpkBuffer *xbuf,
struct XpkPrefsSemaphore *sem)
{
STRPTR bufptr;
struct XpkTypeData *ret = 0;
struct TagItem tag[] = {
{ XPK_FileName, 0},
{ XPK_PackMode, 0},
{ TAG_DONE, 0}};
tag[0].ti_Data = (ULONG) xbuf->xb_Prog.xp_FileName;
tag[1].ti_Data = xbuf->xb_PackingMode;
if((bufptr = (STRPTR) hookread(xbuf, XIO_READ, 0, bufsize)))
{
ret = (((RecogFunc) sem->xps_RecogFunc) (bufptr,
xbuf->xb_RMsg.xmm_FileName, bufsize, xbuf->xb_InLen, tag));
hookread(xbuf, XIO_SEEK, 0, -bufsize);
}
return ret;
}
#endif /* XPKMASTER_OPEN_C */